#include "stdafx.h"
#include "standard/CThrowException.h"
#include "ado/DbMysql.h"
#include "readfile.h"
#include "processlog.h"

DbMysql::DbMysql()
{
    m_dbhost.erase();
    m_dbuser.erase();
    m_dbpass.erase();
    m_dbname.erase();
    m_dbprefix.erase();
    m_dbcharset.erase();	
}

DbMysql* DbMysql::_instance = NULL;

DbMysql* DbMysql::instance()
{
    (_instance == NULL)?_instance = new DbMysql():NULL;
	return _instance; 
}

MYSQL* DbMysql::connect(const char *dbname)
{
    std::string db_host     = get_config(dbname, "host");
    std::string db_user     = get_config(dbname, "user");
    std::string db_pass     = get_config(dbname, "pass");
    std::string db_name     = get_config(dbname, "name");
    std::string db_charset  = get_config(dbname, "charset");
    std::string db_prefix   = get_config(dbname, "prefix");
    
    mysql_init(&this->mysql);
    
    if (!mysql_real_connect(&this->mysql, db_host.c_str(), db_user.c_str(), 
            db_pass.c_str(), db_name.c_str(), 0, NULL, 0)) {
                
        WriteLogTime( "mysql connect failed : " );
		WriteLogTime( mysql_error(&this->mysql) );
		WriteLogTime( "\n" );
    } 
    else {
    
        //WriteLogTime( "mysql connect to " );
        //WriteLog( db_name.c_str() );
        //WriteLog( " succeed !\n" );

        this->execute( ("set names "+db_charset).c_str() );
    }
    
    return &this->mysql;
}

void DbMysql::close(MYSQL *_mysql)
{
    mysql_close(_mysql);
}

void DbMysql::close()
{
    mysql_close(&this->mysql);
}

int DbMysql::MysqlPing(MYSQL* conn)
{
    return mysql_ping(conn);
}

std::string DbMysql::get_dbprefix()
{
    return m_dbprefix;
}

std::string DbMysql::get_defaultdb()
{
    return get_config("db_default","name");
}

std::string DbMysql::get_dbname()
{
    return m_dbname;
}

DbMysql* DbMysql::execute(const char* sql)
{
    int myint;
    
    //llog( "QUERY : %s\n" , sql);    
	if (( myint = mysql_query(&this->mysql,sql) )) {
		throw CThrowException(mysql_error(&this->mysql), 0);
	}
		
	this->_results = mysql_store_result(&this->mysql);	
	return this;
}

int DbMysql::insert_id()
{
    return (int)mysql_insert_id(&this->mysql);
}

std::map<std::string, std::string> DbMysql::getRow()
{
    MYSQL_ROW       sqlrow;
    MYSQL_FIELD*    mysql_field;
    MYSQL_RES*      results;
    
    std::map<std::string, std::string> resRow;
    unsigned int field_count;    
       
    results = this->_results; 
       
    if (results) {              
        sqlrow = mysql_fetch_row(results);
        
        if (this->getNumRow() > 0) {
            mysql_field_seek(results, 0);
            for ( field_count = 0; field_count < mysql_num_fields(results); field_count++) {
                mysql_field = mysql_fetch_field(results);
                if (sqlrow[field_count]) { 
                    resRow[mysql_field->name] = sqlrow[field_count];            
                } 
                else {
                    resRow[mysql_field->name] = "NULL";
                }
            }            
        }                    
                
        if (mysql_errno(&mysql)) 
			throw CThrowException(mysql_error(&this->mysql));        
    }
    mysql_free_result(results);
    return resRow;
}

std::map<unsigned long int, std::map<std::string, std::string> > DbMysql::getArray()
{
    MYSQL_ROW       sqlrow;
    MYSQL_FIELD*    mysql_field;
    MYSQL_RES*      results;
    
    std::map<unsigned long int, std::map<std::string, std::string> > resRow;
    
    unsigned long int row_count;
    unsigned long int field_count;    
       
    results = this->_results;
       
    if (results) {     
        for (row_count = 0; (sqlrow = mysql_fetch_row(results)); row_count++) { 
            mysql_field_seek(results, 0);
            for (field_count = 0; field_count < mysql_num_fields(results); field_count++) {    
                mysql_field = mysql_fetch_field(results);        
                if (sqlrow[field_count]) {                     
                    resRow[row_count][mysql_field->name] = sqlrow[field_count];
                } 
                else {
                    resRow[row_count][mysql_field->name] = "NULL";
                }
            }
        }        
        if (mysql_errno(&mysql)) throw CThrowException(mysql_error(&this->mysql));                
    }
    mysql_free_result(results);
    
    return resRow;
}

MYSQL_RES* DbMysql::getResult()
{
    return mysql_store_result(&this->mysql);
}

int DbMysql::getNumField()
{
	return mysql_num_fields(this->_results);
}

//get field as array
std::map<unsigned long int, std::string> DbMysql::getArrayField()
{
    std::map<unsigned long int, std::string> field_arr;
    MYSQL_ROW      mysql_field;
    MYSQL_RES*      results;
    
    results = this->_results;
    mysql_field_seek(results, 0);
    
    for (unsigned int field_count = 0; (mysql_field = mysql_fetch_row(results)); field_count++)
    {
        field_arr[field_count] = mysql_field[0];
    } 

    return field_arr;
}

unsigned long int DbMysql::getNumRow()
{
	int num_rows = (int)mysql_num_rows(this->_results);
	return num_rows;
}

#if IF_TEST_DBMYSQL
/**
 *  create table le_search_good (
     `search_good_id`    int(11) primary key auto_increment,
     `goods_name`        varchar(100),
     `price`             decimal(11,2),
     `yuan_price`        decimal(11,2),
     `quality`           int(11),
     `fee`               varchar(100)
 );
 */
/*int main()
{
    std::map<unsigned int, std::map<std::string, std::string> > rows;
    
   
    DbMysql::instance()->execute("insert into le_search_good (goods_name, price, yuan_price) values ('test1', '99.00', '199.00')");     
    rows = DbMysql::instance()->execute("select goods_name, price, yuan_price from le_search_good")->getArray();
    
    for (unsigned int i=0; i<rows.size(); i++)
    {
        std::cout << "goods_name:"    <<  rows[i]["goods_name"]   <<  std::endl;
        std::cout << "price:"         <<  rows[i]["price"]        <<  std::endl;
        std::cout << "yuan_price:"    <<  rows[i]["yuan_price"]   <<  std::endl;
    }
    
    DbMysql::instance()->close();
    
    return 0;
}*/


/**
 *  g++ DbMysql.cpp Exception.cpp -o dbmysql -lmysqlclient -L/usr/local/mysql/lib
 */
#endif
